﻿#include "scriptmanager.h"
#include "cmainframe.h"
#include "nodemanager/wbasenode.h"
#include "nodemanager/wmountnode.h"
#include "nodemanager/wsignallampnode.h"
#include "nodemanager/wswitchnode.h"
#include "nodemanager/wnodemanager.h"

#include <functional>

initialiseSingleton(ScriptManager);

ScriptManager::ScriptManager()
    : m_lua_state(NULL)
{

}

ScriptManager::~ScriptManager()
{
    lua_exit();
}

/// 初始化
bool ScriptManager::lua_init()
{
    m_lua_state = luaL_newstate();
    if(m_lua_state)
    {
        luaL_openlibs(m_lua_state);
        luaopen_cjson(m_lua_state);

        LOGI("lua_init successed.");
    }

    return m_lua_state != NULL ? true : false;
}

/// 退出
void ScriptManager::lua_exit()
{
    if (m_lua_state != NULL)
    {
        lua_close(m_lua_state);
        m_lua_state = NULL;

        LOGI("lua_exit successed.");
    }
}

/**
 * @brief 为 Lua 状态创建独立环境
 * @param inheritGlobals 是否继承全局函数和库（true=继承，false=完全干净的环境）
 * @return 是否成功创建独立环境
 */
bool ScriptManager::CreateIsolatedLuaEnvironment(bool inheritGlobals)
{
    if (!m_lua_state) return false;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 1. 清除栈上所有内容
    lua_settop(m_lua_state, 0);

    // 2. 创建新的环境表
    lua_newtable(m_lua_state);  // 创建环境表

    if (inheritGlobals)
    {
        // 3a. 如果需要继承全局函数，设置元表访问全局环境
        lua_getglobal(m_lua_state, "_G");  // 获取全局表（替代 LUA_GLOBALSINDEX）
        lua_setmetatable(m_lua_state, -2); // 设置为新环境的元表

        // 可选：复制常用基础库到新环境
        static const char* const basicLibs[] = {
            "_G", "math", "table", "string", nullptr
        };

        for (const char* const* lib = basicLibs; *lib; ++lib)
        {
            lua_getglobal(m_lua_state, *lib);
            lua_setfield(m_lua_state, -2, *lib);
        }
    }
    else
    {
        // 3b. 或者创建完全干净的环境
        lua_newtable(m_lua_state);  // 创建空的元表
        lua_setmetatable(m_lua_state, -2);
    }

    // 4. 在 Lua 5.2+ 中设置环境的新方法
    // 首先将环境表存储在注册表中
    lua_pushvalue(m_lua_state, -1);  // 复制环境表
    lua_setfield(m_lua_state, LUA_REGISTRYINDEX, "my_isolated_env");  // 存储在注册表中

    // 然后为当前线程设置环境
    lua_rawgeti(m_lua_state, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS);  // 获取全局环境
    lua_pushvalue(m_lua_state, -2);  // 推入我们的环境表
    lua_setmetatable(m_lua_state, -2);  // 设置为全局环境的元表
    lua_pop(m_lua_state, 1);  // 弹出全局环境

    // 5. 执行垃圾回收确保干净状态
    lua_gc(m_lua_state, LUA_GCCOLLECT, 0);

    return true;
}

/// 导入指定文件脚本并执行
bool ScriptManager::exe_lua_string_for_file(wxString scriptFile)
{
    if(!wxFileExists(scriptFile)) return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxMemoryBuffer pMemorybuffer;
    if(!ReadFileToMemoryBuffer(scriptFile,pMemorybuffer))
    {
        LOGW(wxString("脚本文件导入失败:"+scriptFile).ToStdString().c_str());
        return false;
    }

    wxString tmpfilename = scriptFile.Mid(scriptFile.find_last_of("\\")+1);

    if(pMemorybuffer.IsEmpty() ||
       !exe_lua_string(pMemorybuffer,tmpfilename))
    {
        LOGW(wxString("脚本文件导入失败:"+scriptFile).ToStdString().c_str());
        return false;
    }
    else
    {
        LOGI(wxString("脚本文件导入成功:"+scriptFile).ToStdString().c_str());
    }

    return true;
}

/// 导入指定目录所有脚本并执行
bool ScriptManager::exe_lua_string_for_path(wxString scriptPath)
{
    if(scriptPath == "")
        return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxVector<wxString> pdecPaths;
    if(ListFilesInDirectory(scriptPath,pdecPaths))
    {
        for(int i=0;i<pdecPaths.size();i++)
        {
            wxMemoryBuffer pMemorybuffer;
            if(!ReadFileToMemoryBuffer(pdecPaths[i],pMemorybuffer))
            {
                LOGW(wxString("脚本文件导入失败:"+pdecPaths[i]).ToStdString().c_str());
                continue;
            }

            wxString tmpfilename = pdecPaths[i].Mid(pdecPaths[i].find_last_of("\\")+1);

            if(pMemorybuffer.IsEmpty() ||
               !exe_lua_string(pMemorybuffer,tmpfilename))
            {
               LOGW(wxString("脚本文件导入失败:"+pdecPaths[i]).ToStdString().c_str());
               return false;
            }
            else
            {
                LOGI(wxString("脚本文件导入成功:"+pdecPaths[i]).ToStdString().c_str());
            }
        }
    }

    return true;
}

/// 执行脚本
bool ScriptManager::exe_lua_string(wxMemoryBuffer& buffer,wxString filename)
{
    if (m_lua_state == NULL || buffer.IsEmpty())
        return false;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 加载 Lua 代码
    if (luaL_loadbuffer(m_lua_state,
                        (const char*)buffer.GetData(),
                        buffer.GetDataLen(),
                        "interlocker4")) {
        const char* pErrorMsg = lua_tostring(m_lua_state, -1);
        if (pErrorMsg) {
            wxString errStr = wxString::Format("Lua load error:%s:%s",
                                               filename,
                                               pErrorMsg);
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,errStr.ToUTF8());
            LOGE(errStr.ToStdString().c_str());
        }
        lua_pop(m_lua_state, 1); // 弹出错误信息
        return false;
    }

    // 执行 Lua 代码
    int ret = lua_pcall(m_lua_state, 0, 0, 0);
    if (ret != LUA_OK) {
        const char* pErrorMsg = lua_tostring(m_lua_state, -1);
        if (pErrorMsg) {
            // 获取调用栈信息
            luaL_traceback(m_lua_state, m_lua_state, pErrorMsg, 1);
            const char* traceback = lua_tostring(m_lua_state, -1);
            wxString errStr = wxString::Format("Lua runtime error:%s,%s",
                                               filename,
                                               traceback);
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,errStr.ToUTF8());
            LOGE(errStr.ToStdString().c_str());
            lua_pop(m_lua_state, 2); // 弹出错误信息和 traceback
        } else {
            LOGE("Lua runtime error (no message)");
        }
        return false;
    }

    //LOGI("exe_lua_string success.");
    return true;
}

/// 调用结点的鼠标事件接口
void ScriptManager::callLuaFunctionWithBaseNodeMouseEvent(wxString nodeName,wxMouseEvent& event)
{
    if(m_lua_state == NULL || nodeName == "") return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxString decFunction = wxString::Format("onMouseEvent_%s",nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,
                                                  decFunction.ToStdString().c_str());

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(event);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::cllLuaFunctionWithBaseNodeMouseEvent:%s:%s" ,decFunction,e.what()).ToUTF8());
        }
    }
}

/// 调用结点的更新接口
void ScriptManager::callLuaFunctionWithBaseNodeUpdate(wxString nodeName)
{
    if(m_lua_state == NULL || nodeName == "") return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxString decFunction = wxString::Format("update_%s",nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,
                                                  decFunction.ToStdString().c_str());

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFunctionWithBaseNodeDraw:%s:%s" ,decFunction,e.what()).ToUTF8());
        }
    }
}

/// 调用结点的绘制接口
void ScriptManager::callLuaFunctionWithBaseNodeDraw(maindrawscene *pmaindrawscene,wxString nodeName)
{
    if(pmaindrawscene == NULL || m_lua_state == NULL || nodeName == "") return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    wxString decFunction = wxString::Format("draw_%s",nodeName);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state,
                                                  decFunction.ToStdString().c_str());

    if (func.isFunction()) {
        try {
            // 调用Lua函数并传递wxPoint对象
            func(pmaindrawscene);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFunctionWithBaseNodeDraw:%s:%s" ,decFunction, e.what()).ToUTF8());
        }
    }
}

/// 调用网络连接建立成功接口
void ScriptManager::callLuaFunctionWithNetworkConnected(const char *clientid)
{
    if(m_lua_state == NULL) return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "OnProcessConnectedNet");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(clientid);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::OnProcessConnectedNet: %s" , e.what()).ToUTF8());
        }
    }
}

/// 调用服务器消息到达接口
void ScriptManager::callLuaFunctionWithServerMessageCome(const char* clientid,int msgType,const char* message,int msglength)
{
    if(m_lua_state == NULL || message == "") return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "OnProcessNetText");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(clientid,msgType,message,msglength);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::OnProcessNetText: %s" , e.what()).ToUTF8());
        }
    }
}

/// 调用lua系统初始接口
void ScriptManager::callLuaFunctionWithSystemInit()
{
    if(m_lua_state == NULL) return;

    //std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "initsystem");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFunctionWithSystemInit: %s" , e.what()).ToUTF8());
        }
    }
}

/// 调用lua系统鼠标事件接口
void ScriptManager::callLuaFunctionWithSystemMouseEvent(wxMouseEvent& event)
{
    if(m_lua_state == NULL) return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "onMouseEvent");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func(event);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFunctionWithSystemMouseEvent: %s" , e.what()).ToUTF8());
        }
    }
}

/// 调用lua系统更新接口
void ScriptManager::callLuaFuncitonWithSystemUpdate(void)
{
    if(m_lua_state == NULL) return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "updatesystem");

    if (func.isFunction()) {
        try {
            // 调用Lua函数
            func();
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFuncitonWithSystemUpdate: %s" , e.what()).ToUTF8());
        }
    }
}

/// 调用lua主绘制接口
void ScriptManager::callLuaFunctionWithMainDrawScene(maindrawscene *pmaindrawscene)
{
    if(pmaindrawscene == NULL || m_lua_state == NULL) return;

    std::lock_guard<std::mutex> lock(m_luastateMutex);

    // 获取Lua函数
    luabridge::LuaRef func = luabridge::getGlobal(m_lua_state, "maindrawscene");

    if (func.isFunction()) {
        try {
            // 调用Lua函数并传递wxPoint对象
            func(pmaindrawscene);
        } catch (const luabridge::LuaException& e) {
            CMainFrame::getSingleton().printlog(LOG_LEVEL_ERROR,
                                                wxString::Format("ScriptManager::callLuaFunctionWithMainDrawScene: %s" , e.what()).ToUTF8());
        }
    }
}

/// 注册到lua
void ScriptManager::registertoLua(void)
{
    // 注册wxWidgets到脚本
    registerwxWidgetsToLua();

    // 注册系统函数到脚本中
    registerSystemFunToLua();

    // 注册主绘图到脚本
    registermaindrawsceneToLua();

    // 注册结点到脚本
    registerNodeToLua();

    /// 注册STL到脚本中
    registerSTLToLua();

    // 注册结点管理器为全局变量
    this->registerNodeManagertoLua(WNodeManager::getSingletonPtr());
}

/// 注册结点管理器到lua中
void ScriptManager::registerNodeManagertoLua(WNodeManager *manager)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         manager,
                         "nodemanager");
}

/// 注册主窗口到lua中
void ScriptManager::registerMainFrametoLua(CMainFrame *mainframe)
{
    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         mainframe,
                         "system");
}

/// 注册结点到lua中
void ScriptManager::registerBaseNodetoLua(wxString nodeType,WBaseNode* basenode)
{
    if(basenode == NULL || nodeType == "") return;

    // 注册结点为全局变量
    luabridge::setGlobal(m_lua_state,
                         basenode,
                         wxString(nodeType+basenode->getName()).ToStdString().c_str());
}

template<typename T>
static wxVector<T>* createWxVector() {
    return new wxVector<T>();
}

template <typename T> void ScriptManager::registerVector(lua_State* L, const std::string& className)
{
    luabridge::getGlobalNamespace(L)
        .beginClass<wxVector<T>>(className.c_str())
            //.addConstructor<void(*)()>()

            // 成员函数
            .addFunction("size", &wxVector<T>::size)
            .addFunction("at", static_cast<const T& (wxVector<T>::*)(size_t) const>(&wxVector<T>::at))
            .addFunction("empty", &wxVector<T>::empty)
            .addFunction("push_back", static_cast<void (wxVector<T>::*)(const T&)>(&wxVector<T>::push_back))
            .addStaticFunction("create", &createWxVector<T>)  // 使用静态工厂方法
            .addFunction("__gc", std::function<void(wxVector<T>*)>([](wxVector<T>* ptr) { delete ptr; }))
        .endClass();
}

/// 注册STL到脚本中
void ScriptManager::registerSTLToLua(void)
{
    if(m_lua_state == NULL)
        return;

    //registerVector<tagMountPoint>(m_lua_state,"MPVector");
    //registerVector<tagSLRouteNode>(m_lua_state,"RNVector");
    registerVector<wxString>(m_lua_state,"SVector");
}

/// 注册系统函数到脚本中
void ScriptManager::registerSystemFunToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<CMainFrame>("CMainFrame")
        //.addConstructor<void (*)(void)>()

        // 成员函数
        .addFunction("startTimer", &CMainFrame::startTimer)
        .addFunction("stopTimer", &CMainFrame::stopTimer)
        .addFunction("stopAllTimer", &CMainFrame::stopAllTimer)
        .addFunction("printlog", &CMainFrame::printlog)
        .addFunction("getSignals", &CMainFrame::getSignals)
        .addFunction("updateSignals", &CMainFrame::updateSignals)
        .addFunction("sendSignals", &CMainFrame::sendSignals)
        .addFunction("sendSignals2", &CMainFrame::sendSignals2)
        .endClass();
}

namespace wxStringLuaBindings {
static const char* ToUTF8Wrapper(wxString* str) {
    return str->ToUTF8().data();
}
static const char* ToCStrWrapper(wxString* str) {
    return static_cast<const char*>(str->c_str());
}
}

/// 注册wxWidgets到脚本
void ScriptManager::registerwxWidgetsToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxPoint>("wxPoint")
            //.addConstructor<void (*)(void)>()
            .addConstructor<void (*)(int,int)>()

            // 成员变量
            .addProperty("x", &wxPoint::x)
            .addProperty("y", &wxPoint::y)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxRealPoint>("wxRPoint")
            //.addConstructor<void (*)(void)>()
            .addConstructor<void (*)(double,double)>()

            // 成员变量
            .addProperty("x", &wxRealPoint::x)
            .addProperty("y", &wxRealPoint::y)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxSize>("wxSize")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(int,int)>()

            // 成员函数
            .addFunction("GetHeight", &wxSize::GetHeight)
            .addFunction("GetWidth", &wxSize::GetWidth)
            .addFunction("SetHeight", &wxSize::SetHeight)
            .addFunction("SetWidth", &wxSize::SetWidth)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxRect>("wxRect")
            //.addConstructor<void (*)()>()
            //.addConstructor<void (*)(int,int,int,int)>()
            .addConstructor<void (*)(const wxPoint &, const wxSize &)>()

            // 成员函数
            .addFunction("GetTopLeft", &wxRect::GetTopLeft)
            .addFunction("GetTopRight", &wxRect::GetTopRight)
            .addFunction("GetBottomLeft", &wxRect::GetBottomLeft)
            .addFunction("GetBottomRight", &wxRect::GetBottomRight)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxColour>("wxColor")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(unsigned char,unsigned char,unsigned char,unsigned char)>()
            //.addConstructor<void (*)(unsigned long)>()

            // 成员函数
            .addFunction("GetAlpha", &wxColour::Alpha)
            .addFunction("GetBlue", &wxColour::Blue)
            .addFunction("GetGreen", &wxColour::Green)
            .addFunction("GetRed", &wxColour::Red)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxCStrData>("wxCStrData")
            .addFunction("str", &wxCStrData::operator const char*)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxString>("wxString")
            //.addConstructor<void (*)()>()
            .addConstructor<void (*)(const char *)>()
            //.addConstructor<void (*)(const wchar_t *)>()
            //.addConstructor<void (*)(const std::string &)>()

            // 成员函数
            .addFunction("c_str", &wxString::c_str)
            .addFunction("str",&wxStringLuaBindings::ToCStrWrapper)
            .addFunction("toutf8", &wxStringLuaBindings::ToUTF8Wrapper)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginNamespace("MB")
            .addConstant("ANY", static_cast<int>(wxMouseButton::wxMOUSE_BTN_ANY))
            .addConstant("NONE", static_cast<int>(wxMouseButton::wxMOUSE_BTN_NONE))
            .addConstant("LEFT", static_cast<int>(wxMouseButton::wxMOUSE_BTN_LEFT))
            .addConstant("MIDDLE", static_cast<int>(wxMouseButton::wxMOUSE_BTN_MIDDLE))
            .addConstant("RIGHT", static_cast<int>(wxMouseButton::wxMOUSE_BTN_RIGHT))
            .addConstant("AUX1", static_cast<int>(wxMouseButton::wxMOUSE_BTN_AUX1))
            .addConstant("AUX2", static_cast<int>(wxMouseButton::wxMOUSE_BTN_AUX2))
        .endNamespace();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxEvent>("wxEvent")
            //.addConstructor<void (*)(int,wxEventType)>()

        .endClass()
        .beginClass<wxMouseState>("wxMouseState")
            .addConstructor<void (*)()>()

            // 成员函数
            .addFunction("GetPosition",
                         (wxPoint (wxMouseState::*)() const) &wxMouseState::GetPosition)
            .addFunction("GetX", &wxMouseState::GetX)
            .addFunction("GetY", &wxMouseState::GetY)
        .endClass()
        .deriveClass<wxMouseEvent, wxEvent>("wxMouseEvent")
            //.addParent<wxMouseState>()
            .addConstructor<void (*)(int)>()

            // 成员函数
            .addFunction("IsButton", &wxMouseEvent::IsButton)
            .addFunction("Button", &wxMouseEvent::Button)
            .addFunction("ButtonDClick", &wxMouseEvent::ButtonDClick)
            .addFunction("ButtonDown", &wxMouseEvent::ButtonDown)
            .addFunction("ButtonUp", &wxMouseEvent::ButtonUp)
            .addFunction("GetButton", &wxMouseEvent::GetButton)
            .addFunction("GetPosition",
                       (wxPoint (wxMouseEvent::*)() const) &wxMouseEvent::GetPosition)
        .endClass();
}

/// 注册主绘图到脚本
void ScriptManager::registermaindrawsceneToLua(void)
{
    if(m_lua_state == NULL)
        return;
}

/// 注册结点到脚本中
void ScriptManager::registerNodeToLua(void)
{
    if(m_lua_state == NULL)
        return;

    luabridge::getGlobalNamespace(m_lua_state)
        .beginNamespace("MD")
            .addConstant("LEFT", static_cast<int>(MountDirection::DIRECTION_LEFT))
            .addConstant("RIGHT", static_cast<int>(MountDirection::DIRECTION_RIGHT))
        .endNamespace()
        .beginNamespace("NT")
            .addConstant("SWITCH", static_cast<int>(NodeType::NODE_SWITCH))
            .addConstant("SIGNAL", static_cast<int>(NodeType::NODE_SIGNAL))
            .addConstant("MOUNT", static_cast<int>(NodeType::NODE_MOUNT))
        .endNamespace()
        .beginNamespace("NOS")
            .addConstant("CHOSEN", static_cast<int>(NodeOperState::CHOSEN))
            .addConstant("LOCKED", static_cast<int>(NodeOperState::LOCKED))
            .addConstant("NORMAL", static_cast<int>(NodeOperState::NORMAL))
        .endNamespace()
        .beginNamespace("NSS")
            .addConstant("CLEAR", static_cast<int>(NodeSignalState::CLEAR))
            .addConstant("OCCUPY", static_cast<int>(NodeSignalState::OCCUPY))
            .addConstant("NOSIGNAL", static_cast<int>(NodeSignalState::NOSIGNAL))
        .endNamespace()
        .beginNamespace("SS")
            .addConstant("POSITIVE", static_cast<int>(SwitchState::POSITIVE))
            .addConstant("NEGATIVE", static_cast<int>(SwitchState::NEGATIVE))
        .endNamespace();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<wxPolygonEx>("wxPolygonEx")
            .addConstructor<void(*)()>()

            // 成员函数
            .addFunction("append", &wxPolygonEx::append)
            .addFunction("clear", &wxPolygonEx::clear)
            .addFunction("size", &wxPolygonEx::size)
            .addFunction("empty", &wxPolygonEx::empty)
            .addFunction("boundingRect", &wxPolygonEx::boundingRect)
            .addFunction("containsPoint", &wxPolygonEx::containsPoint)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagMountPoint>("tagMountPoint")
            .addConstructor<void(*)(wxString,wxPoint,WBaseNode*,int,int)>()

            // 注册成员变量
            .addProperty("pos", &tagMountPoint::pos)
            .addProperty("screenpos", &tagMountPoint::screenpos)
            .addProperty("node", &tagMountPoint::node)
            .addProperty("level", &tagMountPoint::level)
            .addProperty("direction", &tagMountPoint::direction)
            .addProperty("angle", &tagMountPoint::angle)
            .addProperty("name", &tagMountPoint::name)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<tagSLRouteNode>("tagSLRouteNode")
            .addConstructor<void(*)(WBaseNode*,const int)>()

            // 注册成员变量
            .addProperty("node", &tagSLRouteNode::node)
            .addProperty("MPointIndex", &tagSLRouteNode::MPointIndex)
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<WBaseNode>("WBaseNode")
            .addConstructor<void (*)(const wxString&)>()

            // 成员函数
            .addFunction("getName", &WBaseNode::getName)
            .addFunction("setNodeType", &WBaseNode::setNodeType)
            .addFunction("getNodeType", &WBaseNode::getNodeType)
            .addFunction("setOperState", &WBaseNode::setOperState)
            .addFunction("getOperState", &WBaseNode::getOperState)
            .addFunction("setSignalState", &WBaseNode::setSignalState)
            .addFunction("getSignalState", &WBaseNode::getSignalState)
            .addFunction("setPosition", &WBaseNode::setPosition)
            .addFunction("getPosition", &WBaseNode::getPosition)
            .addFunction("getMountPointByDir", &WBaseNode::getMountPointByDir)
            .addFunction("isExistMountNode", &WBaseNode::isExistMountNode)
            .addFunction("getScreenPosition", &WBaseNode::getScreenPosition)
            .addFunction("getBoundingRect", &WBaseNode::getBoundingRect)
            .addFunction("getColourByState", &WBaseNode::getColourByState)
            .addFunction("getTextColourByState", &WBaseNode::getTextColourByState)
        .endClass()
        .deriveClass<WMountNode, WBaseNode>("WMountNode")
            .addConstructor<void(*)(const wxString&)>()

            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WMountNode*>(base);
            })
        .endClass()
        .deriveClass<WSignalLampNode, WBaseNode>("WSignalLampNode")
            .addConstructor<void(*)(const wxString&)>()

            // 成员函数
            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WSignalLampNode*>(base);
            })
        .endClass()
        .deriveClass<WSwitchNode, WBaseNode>("WSwitchNode")
            .addConstructor<void(*)(const wxString&)>()

            // 成员函数
            .addFunction("initSwitchState", &WSwitchNode::initSwitchState)
            .addFunction("setSwitchState", &WSwitchNode::setSwitchState)
            .addFunction("getSwitchState", &WSwitchNode::getSwitchState)

            .addStaticFunction("castFromBase", +[](WBaseNode* base) {
                return dynamic_cast<WSwitchNode*>(base);
            })
        .endClass();

    luabridge::getGlobalNamespace(m_lua_state)
        .beginClass<WNodeManager>("WNodeManager")
            .addConstructor<void (*)()>()

            // 成员函数
            .addFunction("deleteAllNodes", &WNodeManager::deleteAllNodes)
            .addFunction("getNodeByName", &WNodeManager::getNodeByName)
            .addFunction("getNodeByPoint", &WNodeManager::getNodeByPoint)
            .addFunction("addMountNode", &WNodeManager::addMountNode)
            .addFunction("clear", &WNodeManager::clear)
            .addFunction("loadJsonConfig", &WNodeManager::loadJsonConfig)
            .addFunction("getRoute", &WNodeManager::getRoute)
        .endClass();
}
